package policy

import (
	"emsctrl/public"
	"fmt"
	"math"
	"reflect"
	"runtime"
)

type Bat_stora_pv_ctrl struct {
	P *public.CurrentPolicy
}

func (b *Bat_stora_pv_ctrl) ParaSet(policy *public.CurrentPolicy) {
	//TODO implement me
	b.P = policy
	fmt.Println("implement me")
}

func (p *Bat_stora_pv_ctrl) PcsRemote_check() bool {
	if p.P.RemoteSignal.PcsRemoteState == 1 {
		return true
	} else {
		p.P.RunModeSel.PcsRemoteSet()
		return false
	}
}
func (p *Bat_stora_pv_ctrl) Run() bool {
	//TODO implement me
	fmt.Println("Bat_stora_pv_ctrl run")
	check := p.PcsRemote_check()
	if check == true {
		alarmProcess, process := p.FaultAlarm_Process()
		if process == false {
			return false
		}
		if alarmProcess == true {
			p.Policy_Process()
		} else {
			p.stop_proc()
		}
	}
	return true
}

func (p *Bat_stora_pv_ctrl) FaultAlarm_Process() (bool, bool) {
	//TODO implement me
	fmt.Println("FaultAlarm_Process me")
	fmt.Println(p.P.RemoteSignal.PcsFaultState, p.P.RemoteSignal.PcsAlarmState)
	valueOf := reflect.ValueOf(p.P.RemoteSignal)
	of := reflect.TypeOf(p.P.RemoteSignal)
	for i := 0; i < of.NumField(); i++ {
		fmt.Println(of.Field(i).Name, ":", valueOf.Field(i))
	}

	if p.P.RemoteSignal.PcsFaultState == 1 || p.P.RemoteSignal.BMSFaultState == 1 || p.P.RemoteSignal.PcsEmegstop == 1 {

		return false, false
	}
	if p.P.RemoteSignal.PcsAlarmState == 1 || p.P.RemoteMetering.BmsAlarmLevel > 2 || p.P.RemoteSignal.PcsCommState == 1 {
		return false, true
	}
	return true, true
}

func (p *Bat_stora_pv_ctrl) charge_proc() {
	_, file, line, _ := runtime.Caller(0)
	fmt.Printf("File: %s, Line: %d\n", file, line)
	ChDisMode := float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode)
	if p.P.RemoteMetering.Soc >= p.P.RemoteAdjRemoteCtrMng.RemoteAdj.SocPara.SocMax || p.P.RemoteMetering.BmsAlarmLevel >= 2 {
		p.P.RunModeSel.PcsActivePowerSet(0)
	} else {
		f := p.P.CurrTimeline.Power * ChDisMode
		if p.P.RemoteAdjRemoteCtrMng.RemoteCtrl.GridCapaCtrl == 1 {
			f2 := float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.TransPara.Ratio) *
				p.P.RemoteAdjRemoteCtrMng.RemoteAdj.TransPara.Capacity / 100

			if p.P.RemoteMetering.GridActivePower >= f2 {
				f = (f2 - p.P.RemoteMetering.LoadPower) * ChDisMode
			}
		}

		if p.P.RemoteAdjRemoteCtrMng.RemoteCtrl.GridDemandCtrl == 1 {

		}

		if p.P.RemoteMetering.ChargeStationPower != f {
			if float32(math.Abs(float64(f))) > p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxChargePower {
				p.P.RunModeSel.PcsActivePowerSet(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxChargePower * float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode))
			} else {
				p.P.RunModeSel.PcsActivePowerSet(f)
			}

		}
	}
}

func (p *Bat_stora_pv_ctrl) discharge_proc() {
	_, file, line, _ := runtime.Caller(0)
	fmt.Printf("File: %s, Line: %d\n", file, line)
	var f float32 = 0
	if p.P.RemoteMetering.Soc <= p.P.RemoteAdjRemoteCtrMng.RemoteAdj.SocPara.SocMin || p.P.RemoteMetering.BmsAlarmLevel >= 2 {
		p.P.RunModeSel.PcsActivePowerSet(0)
	} else {
		if p.P.RemoteAdjRemoteCtrMng.RemoteCtrl.AntiRefluxCtrl == 1 {
			if p.P.RemoteAdjRemoteCtrMng.RemoteAdj.AntiReflux.Mode == 0 {
				if p.P.RemoteMetering.GridActivePower < p.P.RemoteAdjRemoteCtrMng.RemoteAdj.AntiReflux.Start {
					f = p.P.RemoteMetering.GridActivePower + p.P.RemoteMetering.BmsActivePower*float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode) -
						p.P.RemoteAdjRemoteCtrMng.RemoteAdj.AntiReflux.Start
				} else if p.P.RemoteMetering.GridActivePower > p.P.RemoteAdjRemoteCtrMng.RemoteAdj.AntiReflux.Start &&
					p.P.RemoteMetering.GridActivePower < p.P.RemoteAdjRemoteCtrMng.RemoteAdj.AntiReflux.End {
					f = p.P.RemoteMetering.GridActivePower + p.P.RemoteMetering.BmsActivePower*float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode) -
						p.P.RemoteAdjRemoteCtrMng.RemoteAdj.AntiReflux.End
				} else {
					f = p.P.CurrTimeline.Power
				}
			} else {
				//pid计算.
			}
			if f > p.P.CurrTimeline.Power {
				f = p.P.CurrTimeline.Power
			}
		} else {
			f = p.P.CurrTimeline.Power
		}
		if p.P.RemoteMetering.ChargeStationPower != f {
			if float32(math.Abs(float64(f))) > p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxDisChargePower {
				p.P.RunModeSel.PcsActivePowerSet(-1 * p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxDisChargePower * float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode))
			} else {
				p.P.RunModeSel.PcsActivePowerSet(-f * float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode))
			}

		}
	}
}

func (p *Bat_stora_pv_ctrl) open_check_proc() bool {
	if p.P.RemoteSignal.PcsOpenState != 1 {
		p.P.RunModeSel.PcsActivePowerSet(0)
		p.P.RunModeSel.PcsOpenSet()
		return false
	} else if p.P.RemoteSignal.PcsRunState == 1 {
		if p.P.RemoteSignal.PcsGridConnState == 1 {
			return true
		} else {
			return false
		}
	} else {
		return false
	}
}

func (p *Bat_stora_pv_ctrl) stop_proc() {
	_, file, line, _ := runtime.Caller(0)
	fmt.Printf("File: %s, Line: %d\n", file, line)
	//val, err := devdata.GetDevRegVal("PCS1", "yt", "T1")
	//fmt.Println("yt:t1", val, err)
	if p.P.RemoteSignal.PcsOpenState == 1 {
		p.P.RunModeSel.PcsCloseSet()
		p.P.RunModeSel.PcsActivePowerSet(0)
	}
}

func (p *Bat_stora_pv_ctrl) idle_proc() {
	_, file, line, _ := runtime.Caller(0)
	fmt.Printf("File: %s, Line: %d\n", file, line)
	if p.P.RemoteMetering.ChargeStationPower != 0 {
		p.P.RunModeSel.PcsActivePowerSet(0)
	}
}

func (p *Bat_stora_pv_ctrl) discharge_trace_proc() {
	_, file, line, _ := runtime.Caller(0)
	fmt.Printf("File: %s, Line: %d\n", file, line)
	if p.P.RemoteMetering.Soc <= p.P.RemoteAdjRemoteCtrMng.RemoteAdj.SocPara.SocMin {
		p.P.RunModeSel.PcsActivePowerSet(0)
		return
	}
	load := p.P.RemoteMetering.GridActivePower - p.P.RemoteMetering.BmsActivePower*float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode)
	load = load * float32(p.P.CurrTimeline.Ratio) / 100
	if load > p.P.CurrTimeline.Power {
		load = p.P.CurrTimeline.Power
	}

	if load > p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxDisChargePower {
		load = p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxDisChargePower
	}
	load *= float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode)
	p.P.RunModeSel.PcsActivePowerSet(-load)
}

func (p *Bat_stora_pv_ctrl) charge_pv_trace_proc() {
	var chLoad float32
	_, file, line, _ := runtime.Caller(0)
	fmt.Printf("File: %s, Line: %d\n", file, line)
	if p.P.RemoteMetering.Soc >= p.P.RemoteAdjRemoteCtrMng.RemoteAdj.SocPara.SocMax {
		p.P.RunModeSel.PcsActivePowerSet(0)
		return
	}
	if p.P.RemoteMetering.PvActivePower > 0 {
		chLoad = p.P.RemoteMetering.PvActivePower
	} else {
		chLoad = 0
	}
	if chLoad > p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxChargePower {
		chLoad = p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxChargePower
		//同时降低光伏发电功率,可控光伏增加控制
		p.P.RunModeSel.PvActivePowerSet(chLoad)
	} else {
		p.P.RunModeSel.PvActivePowerSet(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxChargePower)
	}
	ChDisMode := float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode)
	f := chLoad * ChDisMode
	p.P.RunModeSel.PcsActivePowerSet(f)
}

func (p *Bat_stora_pv_ctrl) discharge_trace_diff() {
	_, file, line, _ := runtime.Caller(0)
	fmt.Printf("File: %s, Line: %d\n", file, line)

	if p.P.RemoteMetering.Soc <= p.P.RemoteAdjRemoteCtrMng.RemoteAdj.SocPara.SocMin {
		p.P.RunModeSel.PcsActivePowerSet(0)
		return
	}

	load := p.P.RemoteMetering.GridActivePower - p.P.RemoteMetering.BmsActivePower*float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode)
	load = load * float32(p.P.CurrTimeline.Ratio) / 100
	if load > p.P.CurrTimeline.TrackPower {
		load -= p.P.CurrTimeline.TrackPower
	}

	if load > p.P.CurrTimeline.Power {
		load = p.P.CurrTimeline.Power
	}

	if load > p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxDisChargePower {
		load = p.P.RemoteAdjRemoteCtrMng.RemoteAdj.MaxDisChargePower
	}
	load *= float32(p.P.RemoteAdjRemoteCtrMng.RemoteAdj.PowerPara.ChargeDischargeMode)
	p.P.RunModeSel.PcsActivePowerSet(-load)
}

func (p *Bat_stora_pv_ctrl) Policy_Process() {
	//TODO implement me
	fmt.Println("implement me")
	//TODO implement me
	fmt.Println("implement me")
	switch p.P.CurrTimeline.Mode {
	case public.CTRL_STOP:
		p.stop_proc()
	case public.CTRL_CHARGE:
		proc := p.open_check_proc()
		if proc == true {
			p.charge_proc()
		}
	case public.CTRL_DISCHARGE:
		proc := p.open_check_proc()
		if proc == true {
			p.discharge_proc()
		}

	case public.CTRL_IDLE:
		proc := p.open_check_proc()
		if proc == true {
			p.idle_proc()
		}
	case public.CTRL_DISCHAGET_TRACE:
		proc := p.open_check_proc()
		if proc == true {
			p.discharge_trace_proc()
		}
	case public.CTRL_CHARGE_PV_TRACE:
		proc := p.open_check_proc()
		if proc == true {
			p.charge_pv_trace_proc()
		}
	case public.CTRL_DISCHARGE_TRACE_DIFF:
		proc := p.open_check_proc()
		if proc == true {
			p.discharge_trace_diff()
		}
	}
}
